package com.bytedance.retrofit2;

import java.io.IOException;
import java.lang.reflect.Type;
import java.util.concurrent.Executor;

final class ExecutorCallAdapterFactory extends CallAdapter.Factory {
    final Executor callbackExecutor;

    ExecutorCallAdapterFactory(Executor callbackExecutor) {
        this.callbackExecutor = callbackExecutor;
    }

    public final CallAdapter<Call<?>> get(Type returnType) {
        if (Utils.getRawType(returnType) != Call.class) {
            return null;
        } else {
            final Type responseType = Utils.e(returnType);
            return new CallAdapter<Call<?>>() {
                @Override
                public <R> Call<?> adapt(Call<R> call) {
                    return new ExecutorCallbackCall(callbackExecutor, call);
                }

                @Override
                public final Type responseType() {
                    return responseType;
                }
            };
        }
    }

    static final class ExecutorCallbackCall<T> implements Call<T> {
        final Executor callbackExecutor;
        final Call<T> delegate;

        ExecutorCallbackCall(Executor callbackExecutor, Call<T> delegate) {
            this.callbackExecutor = callbackExecutor;
            this.delegate = delegate;
        }

        public final ResponseWrapper execute() throws IOException {
            return this.delegate.execute();
        }

        public final void enqueue(final Callback callback) {
            if (callback == null) {
                throw new NullPointerException("callback == null");
            }
            this.delegate.enqueue(new Callback<T>() {
                @Override
                public final void onCacheResponse(final ResponseWrapper response) {
                    callbackExecutor.execute(new Runnable() {
                        @Override
                        public final void run() {
                            if (delegate.isCanceled()) {
                                callback.onErrorResponse(new IOException("Canceled"));
                            } else {
                                callback.onCacheResponse(response);
                            }
                        }
                    });
                }

                public final void onErrorResponse(final Throwable throwable) {
                    callbackExecutor.execute(new Runnable() {
                        @Override
                        public final void run() {
                            callback.onErrorResponse(throwable);
                        }
                    });
                }
            });
        }

        public final void cancel() {
            this.delegate.cancel();
        }

        public final boolean isCanceled() {
            return this.delegate.isCanceled();
        }

        public final Call<T> clone() throws CloneNotSupportedException {
            return new ExecutorCallbackCall(this.callbackExecutor, this.delegate.clone());
        }
    }
}

